package com.ruoyi.service.impl;

import com.ruoyi.service.TcpClientService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@Service
public class TcpClientServiceImpl implements TcpClientService {
    @Value("${tcp.path}")
    private String serverHost;
    @Value("${tcp.prot}")
    private int serverPort;
    private Socket socket;
    private PrintWriter out;
    private BufferedReader in;

    private OutputStream outputStream;
    private InputStream inputStream;


    private static final int FRAME_SIZE = 1490;
    private static final int FS_HEAD = 2000;
    private static final int FS_END = 1000;


    private static byte FS_FLAG = 0x01;            // 数据标识
    private static byte FS_CHANNEL = 0x02;         // 射频通道
    private static int FS_COUNT = 1000;
    private static int FS_N = 2000;
    private static short FS_SIZE = 363;            // 数组长度

    private static byte FS_FILE_C = 0x03;            // //当前发送第i个频谱
    private static byte FS_FILE_N = 0x04;          //发送的频谱个数
    private static float[] FS = new float[363];    // 初始化数组
    private static final int TOTAL_FLOAT_COUNT = 363; // 总float数
    private static final int DOUBLE_SIZE = 8;         // double占8字节
    private static final int INT_SIZE = 4;            // int占4字节
    private static final int FLOAT_SIZE = 4;          // float占4字节
    private static final int HEADER_SIZE =
            2 * DOUBLE_SIZE +   // 前两位double
                    INT_SIZE;
    private static final int FIXED_PART_SIZE = 36; // 固定部分总字节数
    private static final int MAX_FS_SIZE = 363 * 4; // FS数组最大字节数
    public List<CSigSpec>  sendMessage(double min, double max,String caseName,Long userid) throws IOException {
        try {
            // 按需建立连接
            socket = new Socket(serverHost, serverPort);
            outputStream = socket.getOutputStream();
            inputStream = socket.getInputStream();
            ByteBuffer sendbuffer = ByteBuffer.allocate(1494);
            sendbuffer.order(ByteOrder.BIG_ENDIAN);  // 统一使用小端序（本地字节序）

            String data = "example";
            byte[] bytes = data.getBytes(StandardCharsets.UTF_8);

            // 2. 先发送4字节长度（大端序）
            byte[] lengthBytes = new byte[4];
            ByteBuffer.wrap(lengthBytes).putInt(bytes.length);


            // 3. 按顺序写入结构体字段
            sendbuffer.putInt(FS_HEAD);
            System.out.println("FS_HEAD===="+FS_HEAD);
            sendbuffer.put(FS_FILE_N);
            System.out.println("FS_FILE_N===="+FS_FILE_N);
            sendbuffer.put(FS_FILE_C);
            System.out.println("FS_FILE_C===="+FS_FILE_C);
            sendbuffer.put(FS_FLAG);
            System.out.println("FS_FLAG===="+FS_FLAG);
            sendbuffer.put(FS_CHANNEL);
            System.out.println("FS_CHANNEL===="+FS_CHANNEL);
            sendbuffer.putInt(FS_COUNT);
            System.out.println("FS_COUNT===="+FS_COUNT);
            sendbuffer.putInt(FS_N);
            System.out.println("FS_N===="+FS_N);
            sendbuffer.putShort(FS_SIZE);
//            System.out.println("FS_SIZE===="+FS_SIZE);
            for (float f : FS) {
                sendbuffer.putFloat(f);
            }


//            for(float f : FS) {
//                sendbuffer.putFloat(f);
//            }

//            for(int ii = 0 ;ii<128; ii++){
//                sendbuffer.putDouble(min);
//            }

            // 写入结束符
            sendbuffer.putDouble(min);
            System.out.println("FS_REQUEST_S===="+min);
            sendbuffer.putDouble(max);
            System.out.println("FS_REQUEST_N===="+max);
            ByteBuffer buffer33 = ByteBuffer.allocate(4);
            Random rand = new Random();

            // 生成1到100之间的随机数（包括1和100）
//            int randomNum = rand.nextInt(100) + 1;
            sendbuffer.putInt(Math.toIntExact(userid));
            System.out.println("ID===="+101);
            sendbuffer.putInt(FS_END);
            System.out.println("FS_END===="+FS_END);
            System.out.println("===================================================================");
            outputStream.write(sendbuffer.array());


            System.out.println("Data sent successfully");

            //--------------------------------------------------------------------//
            outputStream = socket.getOutputStream();
            inputStream = socket.getInputStream();
            System.out.println("TCP Connected!");
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            // 持续监听服务端消息
            byte[] buffer1 = new byte[1494];
            List<CSigSpec> fsList = new ArrayList<>();
            int recieveN = 0;//当前接收的包数
            int recieveTotalN = 999;//总共需要接收的包数
            int countb = 0 ; //每个包的第几个包
            float[] returnData = new float[0];
            int nextFlag = 0;
            int jumpFlag = 0;
            CSigSpec cSigSpec = null;
            while (dis.read(buffer1) != -1) {
                ByteBuffer buffer = ByteBuffer.wrap(buffer1)
                        .order(ByteOrder.LITTLE_ENDIAN);
                int recieveSize = 0;
//                while (recieveN < recieveTotalN) {
                // 1. 读取并验证数据头
                long header = buffer.getInt() & 0xFFFFFFFFL;//(int)(dis.readInt() & 0xFFFFFFFFL);
                String dd = String.format("Received: 0x%08X", header);
                // 2. 读取固
                // 定部分字段
                //0xFB50AAEF
                FS_TCP_Frame frame = new FS_TCP_Frame();
                System.out.println("开始符===="+dd);
                // frame.FS_HEAD = header;
                //总的包数
                frame.FS_FILE_N =  buffer.get();
                //当前包数
                frame.FS_FILE_C =  buffer.get();


                //如果1个包没接收完，继续接收 ，否则接收下个包
//                    if(frame.FS_FILE_C == recieveN){
                recieveN = frame.FS_FILE_C;
                recieveTotalN = frame.FS_FILE_N;
                System.out.println("正在接收第"+frame.FS_FILE_C+"个包,包长度："+frame.FS_SIZE+" ，共" + recieveTotalN + "个包 ");
                frame.FS_FLAG = buffer.get();
                frame.FS_CHANNEL = buffer.get();
                frame.FS_COUNT =  buffer.getInt() ;
                frame.FS_N = buffer.getInt() ;
                frame.FS_SIZE = buffer.getShort();

                if(countb == 0){
                    cSigSpec = new CSigSpec();
                    //新版
                            byte[] bytes4 = new byte[17]; // 4个float * 4字节
                            ByteBuffer bb2 = ByteBuffer.wrap(bytes4).order(ByteOrder.LITTLE_ENDIAN);
                            byte[] buffer3 = new byte[16];
                            buffer.get(buffer3);
                            ByteBuffer bb = ByteBuffer.wrap(buffer3).order(ByteOrder.LITTLE_ENDIAN);
                            float[] floats = new float[4];
                            for(int i=0; i<4; i++) {
                                floats[i] = bb.getFloat();
                                bb2.putFloat(floats[i]);
                            }//如果是第一个

                            double firstDouble = bb2.getDouble(0);
                            String formattedValue = String.format("%,.2f", firstDouble/1000000); // 转换为不带小数点的字符串
                            double number = Double.parseDouble(formattedValue.replace(",", ""));
                            cSigSpec.dbStartFreq = number;
                            double secondDouble = bb2.getDouble(8);
                            String formattedValue2 = String.format("%,.2f", secondDouble/1000000);
                            double number2 = Double.parseDouble(formattedValue2.replace(",", ""));
                            cSigSpec.dbEndFreq = number2;
                    int totalBytes = HEADER_SIZE + (TOTAL_FLOAT_COUNT - 5-4) * FLOAT_SIZE;


                    byte[] buffer2 = new byte[totalBytes];
                    buffer.get(buffer2);
                    ByteBuffer byteBuffer = ByteBuffer.wrap(buffer2)
                            .order(ByteOrder.BIG_ENDIAN); // 根据C++端字节序设置（通常小端）


                    float[] re1 = new float[358];
                    //老版
//                    double double1 = byteBuffer.getDouble();
//                    String formattedValue = String.format("%,.2f", double1/1000000); // 转换为不带小数点的字符串
//                    double number = Double.parseDouble(formattedValue.replace(",", ""));
//                    cSigSpec.dbStartFreq = number;
//                    double double2 = byteBuffer.getDouble();
//                    String formattedValue2 = String.format("%,.2f", double2/1000000);
//                    double number2 = Double.parseDouble(formattedValue2.replace(",", ""));
//                    cSigSpec.dbEndFreq = number2;
                    // 解析第5位int
                    int intValue = byteBuffer.getInt();
                    cSigSpec.nFFTDataLen = intValue;
                    // 解析剩余float数组（363-5=358个）
                    float[] floatArray1 = new float[TOTAL_FLOAT_COUNT - 5];
                    for (int i = 0; i < 358; i++) {
                        re1[i] = byteBuffer.getFloat();
                    }
                    returnData = concatFloatArrays(returnData,re1);
                    countb ++;
                }else{
                    float[] re1 = new float[363];
                    byte[] bytes4 = new byte[17]; // 4个float * 4字节
                    ByteBuffer bb2 = ByteBuffer.wrap(bytes4).order(ByteOrder.LITTLE_ENDIAN);
                    byte[] buffer3 = new byte[16];
                    buffer.get(buffer3);
                    ByteBuffer bb = ByteBuffer.wrap(buffer3).order(ByteOrder.LITTLE_ENDIAN);
                    float[] floats = new float[4];
                    for(int i=0; i<4; i++) {
                        re1[i] = bb.getFloat();
                    }//如果是第一个

                    int totalBytes = HEADER_SIZE + (TOTAL_FLOAT_COUNT - 5-4) * FLOAT_SIZE;
                    byte[] buffer2 = new byte[totalBytes];
                    buffer.get(buffer2);
                    ByteBuffer byteBuffer = ByteBuffer.wrap(buffer2)
                            .order(ByteOrder.BIG_ENDIAN); // 根据C++端字节序设置（通常小端）

//                    float[] re1 = new float[363];
                    for (int i = 4; i < 358; i++) {
                        re1[i] = byteBuffer.getFloat();
                    }

                    int count = 0;
                    for(int qq = 0 ; qq < re1.length; qq++){

                        if(re1[qq] == 0.0){
                            count++;
                        }
                    }
                    float[] newArray = new float[363-count];
                    int index = 0;
                    for (float num : re1) {
                        if (num != 0.0) {
                            newArray[index++] = num;
                        }
                    }
                    returnData = concatFloatArrays(returnData,newArray);
                    if(count > 0){
                        nextFlag = 1;
                        cSigSpec.fFFTData = returnData;
                        returnData = new float[0];
                    }
                }
//
//                    }else{
//
//                    }
                if(nextFlag == 1){
                    countb = 0;
                    nextFlag = 0;
                    fsList.add(cSigSpec);

                    if((recieveN + 1 )== recieveTotalN){
                        jumpFlag = 1;
                    }
                }
                // 4. 读取剩余字段
                frame.FS_REQUEST_S = buffer.getDouble();
                frame.FS_REQUEST_E = buffer.getDouble();
                    long id = buffer.getInt() & 0xFFFFFFFFL;//(int)(dis.readInt() & 0xFFFFFFFFL);
                    String ids = String.format("Received: 0x%08X", id);
                //frame.FS_END = (int) (buffer.getInt()   & 0xFFFFFFFFL);
                long end = buffer.getInt() & 0xFFFFFFFFL;
                String ss = String.format("Received: 0x%08X", end);
                System.out.println("结束符===="+ss );
                System.out.println("recieveN======"+recieveN);
                System.out.println("recieveTotalN======"+recieveTotalN);
                if(jumpFlag == 1){
                    break;
                }
            }
            return fsList;
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            inputStream.close();
            outputStream.close();
            socket.close();
        }
    }

    private static final int HEADER = 0xFB50AAEF;
    private static final int FOOTER = 0x04AF5510;
    public static class FS_TCP_Frame {
        public int FS_HEAD;

        public byte FS_FILE_N;
        public byte FS_FILE_C;
        public byte FS_FLAG;
        public byte FS_CHANNEL;
        public int FS_COUNT;
        public int FS_N;
        public short FS_SIZE;
        public float[] FS;
        public double FS_REQUEST_S;
        public double FS_REQUEST_E;
        public String name;

        public int FS_END;
    }

    public static  class CSigSpec {
        public double dbStartFreq;
        public double dbEndFreq;
        public int nFFTDataLen;
        public float[] fFFTData;
    }

    public float[] concatFloatArrays(float[] array1, float[] array2) {
        float[] result = new float[array1.length + array2.length];
        System.arraycopy(array1, 0, result, 0, array1.length);
        System.arraycopy(array2, 0, result, array1.length, array2.length);
        return result;
    }






    private void writeInt(OutputStream os, int value) throws IOException {
        os.write((value >> 24) & 0xFF);
        os.write((value >> 16) & 0xFF);
        os.write((value >> 8) & 0xFF);
        os.write(value & 0xFF);
    }

    private void writeFloat(OutputStream os, float value) throws IOException {
        writeInt(os, Float.floatToIntBits(value));
    }

    private void writeDouble(OutputStream os, double value) throws IOException {
        writeLong(os, Double.doubleToLongBits(value));
    }

    private void writeLong(OutputStream os, long value) throws IOException {
        os.write((int)(value >> 56));
        os.write((int)(value >> 48));
        os.write((int)(value >> 40));
        os.write((int)(value >> 32));
        os.write((int)(value >> 24));
        os.write((int)(value >> 16));
        os.write((int)(value >> 8));
        os.write((int)value);
    }

}